home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C ++ / Frameworks / MacZoop 1.6.5 / More Classes / File Classes / ZFile.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-17  |  13.5 KB  |  543 lines  |  [TEXT/CWIE]

  1. /*************************************************************************************************
  2. *
  3. *
  4. *            ObjectMacZapp        -- a standard Mac OOP application template
  5. *
  6. *
  7. *
  8. *            ZFile.cpp    -- a generic file object
  9. *
  10. *
  11. *
  12. *
  13. *
  14. *            © 1996, Graham Cox
  15. *
  16. *
  17. *
  18. *
  19. *************************************************************************************************/
  20.  
  21. #include    "ZFile.h"
  22. #include    "MacZoop.h"
  23.  
  24.  
  25. /*-------------------------------***  CONSTRUCTOR  ***----------------------------------*/
  26.  
  27.     
  28.  
  29. ZFile::ZFile( const FSSpec& aSpec )
  30.     : ZComrade()
  31. {
  32.     itsSpec = aSpec;
  33.     
  34.     InitFile();
  35. }
  36.  
  37.  
  38. /*-------------------------------***  CONSTRUCTOR  ***----------------------------------*/
  39.  
  40. ZFile::ZFile( Str255 fName )
  41. {
  42.     short    vRefNum;
  43.     
  44.     FailOSErr( GetVol( NULL, &vRefNum ));
  45.     FailOSErr( FSMakeFSSpec( vRefNum, 0, fName, &itsSpec ));
  46.     
  47.     InitFile();
  48. }
  49.  
  50.  
  51. /*-------------------------------***  DESTRUCTOR  ***----------------------------------*/
  52.  
  53. ZFile::~ZFile()
  54. {
  55.     Close();
  56.     CloseResFork();
  57. }
  58.  
  59.  
  60. /*---------------------------------***  INITFILE  ***----------------------------------*/
  61. /*
  62.     common construction
  63.  
  64. ---------------------------------------------------------------------------------------*/
  65.  
  66. void    ZFile::InitFile()
  67. {
  68.     refNum = _NOT_OPEN;
  69.     resRefNum = _NOT_OPEN;
  70.     isSafeSave = FALSE;
  71.     itsType = kUnknownType;
  72.     
  73.     ssFSpec = itsSpec;
  74.     
  75.     // if the file already exists, get the file type
  76.     // from the file. If file not found, its type is not yet defined.
  77.     
  78.     FInfo    finderInfo;
  79.     
  80.     if( FSpGetFInfo( &itsSpec, &finderInfo ) == noErr )
  81.         itsType = finderInfo.fdType;
  82.         
  83.     GetDateTime((unsigned long*) &qd.randSeed );
  84. }
  85.  
  86.  
  87. /*------------------------------------***  OPEN  ***-----------------------------------*/
  88. /*
  89. Open the file ready for reading or writing
  90. ---------------------------------------------------------------------------------------*/
  91.  
  92. void    ZFile::Open()
  93. {
  94.     FailOSErr( FSpOpenDF( &itsSpec, fsCurPerm, &refNum ));
  95.     SetMark( 0 );
  96. }
  97.  
  98.  
  99. /*----------------------------------***  OPENSAFE  ***---------------------------------*/
  100. /*
  101. Open the file ready for writing via a safe-save temp file
  102. ---------------------------------------------------------------------------------------*/
  103.  
  104. void    ZFile::OpenSafe()
  105. {
  106.     // the file is to opened for a safe save. This creates a temporary file in the same place
  107.     // as the original, but with a name built from part of the original plus a random number.
  108.     // The file is set to be invisible in the Finder. When the file is later closed, the
  109.     // catalogue entries will be swapped and the temp file deleted.
  110.         
  111.     long    tfRand;
  112.     Str31    tfName;
  113.     
  114.     ssFSpec = itsSpec;
  115.     tfRand = ((unsigned long) Random() << 16L ) + Random();
  116.     
  117.     NumToString( ABS( tfRand ), tfName );
  118.     
  119.     // use up to the first 10 chars of the true name, then append our random characters
  120.     
  121.     ssFSpec.name[0] = MIN( ssFSpec.name[0], 10 );
  122.     ConcatPStrings( ssFSpec.name, tfName );
  123.     
  124.     // create and open the file
  125.     
  126.     FailOSErr( FSpCreate( &ssFSpec, gAppSignature, 'temp', smSystemScript ));
  127.     FailOSErr( FSpOpenDF( &ssFSpec, fsCurPerm, &refNum ));
  128.     SetMark( 0 );
  129.     
  130.     // set this file invisible
  131.     
  132.     FInfo    fi;
  133.     
  134.     FailOSErr( FSpGetFInfo( &ssFSpec, &fi ));
  135.     fi.fdFlags |= fInvisible;
  136.     FailOSErr( FSpSetFInfo( &ssFSpec, &fi ));
  137.     
  138.     isSafeSave = TRUE;    
  139. }
  140.  
  141.  
  142. /*------------------------------------***  CLOSE  ***----------------------------------*/
  143. /*
  144.     closes the file, if open
  145. ---------------------------------------------------------------------------------------*/
  146.  
  147. void    ZFile::Close()
  148. {
  149.     if (( refNum != _NOT_OPEN ) &&
  150.         ( refNum != 0 ))
  151.         FailOSErr( FSClose( refNum ));
  152.         
  153.     refNum = _NOT_OPEN;
  154.     
  155.     // if we are closing after a safe-save, swap the files and delete the temp file, AND,
  156.     // if the original file doesn't exist, create it before swapping it.
  157.     
  158.     if( isSafeSave )
  159.     {
  160.         if (! IsReal())
  161.             Create();
  162.         
  163.         FailOSErr( FSpExchangeFiles( &itsSpec, &ssFSpec ));
  164.         FailOSErr( FSpDelete( &ssFSpec ));
  165.     
  166.         isSafeSave = FALSE;
  167.     }
  168. }
  169.  
  170.  
  171. /*-----------------------------------***  CREATE  ***----------------------------------*/
  172. /*
  173. create the file on disk. This does not open it.
  174. ---------------------------------------------------------------------------------------*/
  175.  
  176. void    ZFile::Create()
  177. {
  178.     FailOSErr( FSpCreate( &itsSpec, gAppSignature, itsType, smSystemScript ));
  179. }
  180.  
  181.  
  182. /*-----------------------------------***  DISCARD  ***---------------------------------*/
  183. /*
  184. deletes the file after closing it if necessary
  185. ---------------------------------------------------------------------------------------*/
  186.  
  187. void    ZFile::Discard()
  188. {
  189.     if (refNum != _NOT_OPEN )
  190.         Close();
  191.         
  192.     FailOSErr( FSpDelete( &itsSpec ));
  193. }
  194.  
  195.  
  196. /*------------------------------***  OPENRESFORK  ***----------------------------------*/
  197. /*
  198.     opens the files's resource fork
  199.  
  200. ---------------------------------------------------------------------------------------*/
  201.  
  202. void    ZFile::OpenResFork()
  203. {
  204.     if ( isSafeSave )
  205.         resRefNum = FSpOpenResFile( &ssFSpec, fsCurPerm );
  206.     else
  207.         resRefNum = FSpOpenResFile( &itsSpec, fsCurPerm );
  208.     FailOSErr((resRefNum == -1)? fnfErr : noErr );
  209. }
  210.  
  211.  
  212. /*-----------------------------***  CLOSERESFORK  ***----------------------------------*/
  213. /*
  214. Closes the resource fork, if open
  215. ---------------------------------------------------------------------------------------*/
  216.  
  217. void    ZFile::CloseResFork()
  218. {
  219.     if ( resRefNum != _NOT_OPEN )
  220.     {
  221.         CloseResFile( resRefNum );
  222.         FailOSErr( ResError() );
  223.     }
  224.     resRefNum = _NOT_OPEN;
  225. }
  226.  
  227.  
  228. /*----------------------------***  CREATERESFORK  ***----------------------------------*/
  229. /*
  230. Creates the resource fork, but does not open it
  231. ---------------------------------------------------------------------------------------*/
  232.  
  233. void    ZFile::CreateResFork()
  234. {
  235.     if ( isSafeSave )
  236.         FSpCreateResFile( &ssFSpec, gAppSignature, itsType, smSystemScript );
  237.     else
  238.         FSpCreateResFile( &itsSpec, gAppSignature, itsType, smSystemScript );
  239.     FailOSErr( ResError());
  240. }
  241.  
  242.  
  243. /*----------------------------------***  READ  ***-------------------------------------*/
  244. /*
  245. Read some data (<howMuch> bytes, from current mark) from the file into a buffer
  246. ---------------------------------------------------------------------------------------*/
  247.  
  248. void    ZFile::Read( Ptr inBuffer, long* howMuch )
  249. {
  250.     FailOSErr( isSafeSave? permErr : noErr );
  251.     FailOSErr( FSRead( refNum, howMuch, inBuffer ));
  252. }
  253.  
  254. /*---------------------------------***  WRITE  ***-------------------------------------*/
  255. /*
  256. Write data from the buffer to the file, <howMuch> bytes written from current mark.
  257. ---------------------------------------------------------------------------------------*/
  258.  
  259. void    ZFile::Write( Ptr outBuffer, long* howMuch )
  260. {
  261.     FailOSErr( FSWrite( refNum, howMuch, outBuffer ));
  262. }
  263.  
  264.  
  265. /*---------------------------------***  READ  ***--------------------------------------*/
  266. /*
  267. Reads the entire file into a Handle. The handle is resized initially to the size of the
  268. file. This technique is unsuitable for large files.
  269. ---------------------------------------------------------------------------------------*/
  270.  
  271. void    ZFile::Read( Handle aHandle )
  272. {
  273.     long    howMuch;
  274.     char    hs;
  275.     
  276.     FailNIL( aHandle );
  277.     FailOSErr( isSafeSave? permErr : noErr );
  278.     
  279.     // the handle is sized to the size of the rest of the data in the file, that is, the
  280.     // length less the current position. Override this for different behaviour.
  281.     
  282.     howMuch = GetLength() - GetMark();
  283.     SetHandleSize( aHandle, howMuch );
  284.     
  285.     FailOSErr( MemError());
  286.     
  287.     hs = HGetState( aHandle );
  288.     HLock( aHandle );
  289.     Read( *aHandle, &howMuch );
  290.     HSetState( aHandle, hs );    
  291. }
  292.  
  293.  
  294. /*---------------------------------***  WRITE  ***-------------------------------------*/
  295. /*
  296. Writes a handle to the file from the current mark.
  297. ---------------------------------------------------------------------------------------*/
  298.  
  299. void    ZFile::Write( Handle aHandle )
  300. {
  301.     long    howMuch;
  302.     char    hs;
  303.  
  304.     FailNIL( aHandle );
  305.     
  306.     howMuch = GetHandleSize( aHandle );
  307.     
  308.     hs = HGetState( aHandle );
  309.     HLock( aHandle );
  310.     Write( *aHandle, &howMuch );
  311.     HSetState( aHandle, hs );
  312.     
  313.     // set the length of the file to the current mark, in case the file was
  314.     // shortened. This is OK even if multiple calls are made to this method.
  315.     
  316.     SetLength( GetMark());    
  317. }
  318.  
  319.  
  320. /*---------------------------------***  SETMARK  ***-----------------------------------*/
  321. /*
  322. move the file's mark to the absolute position <aMark>. Mark is set to 0 on Open.
  323. ---------------------------------------------------------------------------------------*/
  324.  
  325. void    ZFile::SetMark( const long aMark )
  326. {
  327.     FailOSErr( SetFPos( refNum, fsFromStart, aMark ));
  328. }
  329.  
  330. /*--------------------------------***  SETTYPE  ***------------------------------------*/
  331. /*
  332. set the type of the file as used in subsequent Create() calls, or if the file already
  333. exists, this changes the file's type on disk. Use with care, since the content of a file
  334. may be totally invalidated by this call.
  335. ---------------------------------------------------------------------------------------*/
  336.  
  337. void    ZFile::SetType( const OSType aType )
  338. {
  339.     if (aType != itsType)
  340.     {    
  341.         itsType = aType;
  342.         
  343.         if ( IsReal())
  344.         {
  345.             FInfo    fi;
  346.             
  347.             FailOSErr( FSpGetFInfo( &itsSpec, &fi ));
  348.             fi.fdType = itsType;
  349.             FailOSErr( FSpSetFInfo( &itsSpec, &fi ));
  350.         }    
  351.     }
  352. }
  353.  
  354.  
  355. /*--------------------------------***  GETMARK  ***--------------=---------------------*/
  356. /*
  357. Get the current position of the file
  358. ---------------------------------------------------------------------------------------*/
  359.  
  360. long    ZFile::GetMark()
  361. {
  362.     long    mark = 0;
  363.     
  364.     FailOSErr( GetFPos( refNum, &mark ));
  365.     
  366.     return mark;
  367. }
  368.  
  369. /*--------------------------------***  GETFSSPEC  ***----------------------------------*/
  370. /*
  371. get the file specification record of the file. You can get the name from this.
  372. ---------------------------------------------------------------------------------------*/
  373.  
  374. void    ZFile::GetFSSpec( FSSpec* aSpec )
  375. {
  376.     *aSpec = itsSpec;
  377. }
  378.  
  379.  
  380. /*-------------------------------***  SETRESFORK  ***----------------------------------*/
  381. /*
  382. sets the resfork of this file to be the current resource file, and returns the one set
  383. originally. This will only work if the res fork exists and is open.
  384. ---------------------------------------------------------------------------------------*/
  385.  
  386. void    ZFile::SetResFork(short* curRes)
  387. {
  388.     *curRes = CurResFile();
  389.     
  390.     if ( resRefNum != _NOT_OPEN )
  391.         UseResFile( resRefNum );
  392. }
  393.  
  394.  
  395. /*-------------------------------***  GETLENGTH  ***-----------------------------------*/
  396. /*
  397. Get the length of the file.
  398. ---------------------------------------------------------------------------------------*/
  399.  
  400. long    ZFile::GetLength()
  401. {
  402.     long    len = 0;
  403.     
  404.     FailOSErr( GetEOF( refNum, &len ));
  405.     
  406.     return len;
  407. }
  408.  
  409.  
  410. /*--------------------------------***  SETLENGTH  ***----------------------------------*/
  411. /*
  412. set the length of the file. You should call this after updating a file in case it got
  413. shorter. Write() with a handle argument does this automatically.
  414. ---------------------------------------------------------------------------------------*/
  415.  
  416. void    ZFile::SetLength( const long aLength )
  417. {
  418.     FailOSErr( SetEOF( refNum, aLength ));
  419. }
  420.  
  421.  
  422. /*--------------------------------***  GETTYPE  ***------------------------------------*/
  423. /*
  424. get the file's type
  425. ---------------------------------------------------------------------------------------*/
  426.  
  427. OSType    ZFile::GetType()
  428. {
  429.     return itsType;
  430. }
  431.  
  432. /*-----------------------------***  HASRESFORK  ***------------------------------------*/
  433. /*
  434. does this file have a resource fork? (n.b. if file not created yet, returns false)
  435. ---------------------------------------------------------------------------------------*/
  436.  
  437. Boolean    ZFile::HasResFork()
  438. {
  439.     Str31            fName;
  440.     CInfoPBRec        pb;
  441.     OSErr            theErr;
  442.     
  443.     if ( isSafeSave )
  444.         CopyPString( ssFSpec.name, fName );
  445.     else
  446.         CopyPString( itsSpec.name, fName );
  447.     
  448.     pb.hFileInfo.ioCompletion = NULL;
  449.     pb.hFileInfo.ioNamePtr = fName;
  450.     pb.hFileInfo.ioVRefNum = itsSpec.vRefNum;
  451.     pb.hFileInfo.ioDirID = itsSpec.parID;
  452.     pb.hFileInfo.ioFDirIndex = 0;
  453.     
  454.     theErr = PBGetCatInfoSync( &pb );
  455.     
  456.     if (theErr)
  457.         return FALSE;
  458.     else
  459.     {
  460.         // see if any physical bytes are alloted to the resource fork
  461.         
  462.         return( pb.hFileInfo.ioFlRPyLen > 0 );
  463.     }        
  464. }
  465.  
  466.  
  467. /*-----------------------------***  HASDATAFORK  ***-----------------------------------*/
  468. /*
  469. does this file have a data fork? (n.b. if file not created yet, returns false)
  470. ---------------------------------------------------------------------------------------*/
  471.  
  472. Boolean    ZFile::HasDataFork()
  473. {
  474.     Str31            fName;
  475.     CInfoPBRec        pb;
  476.     OSErr            theErr;
  477.     
  478.     if ( isSafeSave )
  479.         CopyPString( ssFSpec.name, fName );
  480.     else
  481.         CopyPString( itsSpec.name, fName );
  482.     
  483.     pb.hFileInfo.ioCompletion = NULL;
  484.     pb.hFileInfo.ioNamePtr = fName;
  485.     pb.hFileInfo.ioVRefNum = itsSpec.vRefNum;
  486.     pb.hFileInfo.ioDirID = itsSpec.parID;
  487.     pb.hFileInfo.ioFDirIndex = 0;
  488.     
  489.     theErr = PBGetCatInfoSync( &pb );
  490.     
  491.     if (theErr)
  492.         return FALSE;
  493.     else
  494.     {
  495.         // see if any physical bytes are alloted to the data fork
  496.         
  497.         return( pb.hFileInfo.ioFlPyLen > 0 );
  498.     }        
  499. }
  500.  
  501.  
  502. /*--------------------------------***  ISREAL  ***-------------------------------------*/
  503. /*
  504. does this file exist on the physical diskdrive (or network volume)?
  505. ---------------------------------------------------------------------------------------*/
  506.  
  507. Boolean    ZFile::IsReal()
  508. {
  509.     OSErr    theErr;
  510.     FInfo    fi;
  511.     
  512.     theErr = FSpGetFInfo( &itsSpec, &fi );
  513.     return (theErr == noErr);
  514. }
  515.  
  516.  
  517. /*-------------------------------***  ISLOCKED  ***------------------------------------*/
  518. /*
  519. is this file locked?
  520. ---------------------------------------------------------------------------------------*/
  521.  
  522. Boolean    ZFile::IsLocked()
  523. {
  524.     OSErr    theErr;
  525.     FInfo    fi;
  526.     
  527.     theErr = FSpGetFInfo( &itsSpec, &fi );
  528.     return (( theErr == noErr ) &&
  529.             ( fi.fdFlags & 0x1000 ));
  530. }
  531.  
  532.  
  533. /*---------------------------------***  ISOPEN  ***------------------------------------*/
  534. /*
  535. is this file currently open?
  536. ---------------------------------------------------------------------------------------*/
  537.  
  538. Boolean    ZFile::IsOpen()
  539. {
  540.     return ( refNum != _NOT_OPEN );
  541. }
  542.  
  543.